package com.nxy.cpfsfe.busi.bolag;

import com.adtec.starring.datapool.EPOper;
import com.adtec.starring.exception.BaseException;
import com.adtec.starring.struct.dta.DtaInfo;
import com.adtec.starring.util.SpringUtil;
import com.nxy.cpfsfe.enumtype.*;
import com.nxy.cpfsfe.mybatis.mapper.*;
import com.nxy.cpfsfe.mybatis.pojo.*;
import com.nxy.cpfsfe.service.CpfsService;
import com.nxy.cpfsfe.util.DateUtil;
import com.nxy.cpfsfe.util.ResponseUtil;
import com.nxy.cpfsfe.util.RpcCommUtil;
import com.nxy.cpfsfe.util.XmlUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.*;
import java.util.Map.Entry;

public class NCSOtsNtcProcSrvBean implements CpfsService {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(NCSOtsNtcProcSrvBean.class);
	
	@Override
	public void doService() {
		otsNtcProc();
	}
	
	/**
	 * 
	 * Description:NCS其他通知处理，接收NCS系统的运行状态变更、清算账户余额通知等系统管理相关的报文处理
	 *
	 * @author jjw
	 * @data 2019年8月24日
	 */
	public void otsNtcProc(){
		
		try{
			String tpId = DtaInfo.getInstance().getTpId();
			String bizMsg = (String)EPOper.get(tpId, "ReqBean[0].body[0].BizMsg");
			LOGGER.info("接收到NCS通知报文：[{}]",bizMsg);
			Map<String,String> bizMap = XmlUtil.xml2Map(bizMsg);
			String ntcCont = XmlUtil.getXmlByXPath(bizMsg, "/transaction/body").replaceAll(" ", "");
			String msgId = XmlUtil.getValByXPath(bizMsg, "//MsgId");
			ntcCont = ntcCont.length() > 2000 ? ntcCont.substring(0,2000) : ntcCont;
			bizMap.put("ntcCont",ntcCont);
			bizMap.put("msgId",msgId);
			LOGGER.info("接收到NCS通知报文解包后bizMap：[{}]",bizMap);
			String msgCd = bizMap.get("/transaction/header/msg/msgCd");

			try{
				//登记通知表
				regToSysNtc(bizMap);
				switch(msgCd){
					case "NPS.362.001.01":
						clrgAcctBalWarnNtc(bizMap);
						break;
					case "NPS.360.001.01":
						clrgAcctBalOdNtc(bizMap);
						break;
					case "NPS.366.001.01":
						clrgAcctBalNtc(bizMap);
						break;
					case "NPS.801.001.01":
						sysStaUpdtNtc(bizMap);
						break;
					case "NPS.807.001.01":
						frcOflNtc(bizMap);
						break;
					case "NPS.809.001.01":
						otlStrtupNtc(bizMap);
						break;
					case "NPS.803.001.01":
						mbrOStaUpdtNtc(bizMap);
						break;
					default:
						LOGGER.info("[{}]通知报文不属于NCS通知处理服务范畴",msgCd);

                        return;
				}
			}catch(Exception e){
				LOGGER.error(msgCd + "通知报文处理流程异常",e);
			}
			//判断如果是老系统，则转发通知报文，801报文需添加一个新行号单独处理日切
			ToParm toParm = queryBnoCls(bizMap.get("/transaction/header/msg/rcvMbrCd"),DataTypeEnum.BIZSYS.getCode());
			if(MsgCdOrTpEnum.MSGCD_801.getCode().equals(msgCd)){
				ToParm toParm801 = queryBnoCls(bizMap.get("/transaction/header/msg/rcvMbrCd"),DataTypeEnum.BIZSYS_SWITCHDAY.getCode());
				if(toParm!=null){
					returnGwProc(bizMsg,toParm.getDataCd());
				}else if(toParm801!=null){
					returnGwProc(bizMsg,toParm801.getDataCd());
				}else{
					returnNPS990(bizMap);
				}
			}else {
				if(toParm!=null){
					returnGwProc(bizMsg,toParm.getDataCd());
				}
			}
			LOGGER.info("[{}]通知报文处理成功",msgCd);
		}catch(Exception e){
			LOGGER.error("NCS通知报文解析异常",e);
		}
		
	}
	
	/**
	 * 
	 * Description:NPS.362.001.01-清算账户余额预警报文
	 *
	 * @author yuzh
	 * @data 2019年8月24日
	 */
	private void clrgAcctBalWarnNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.362.001.01-清算账户余额预警报文");
		String sndDt = bizMap.get("/transaction/header/msg/sndDt");
		String sndTm = bizMap.get("/transaction/header/msg/sndTm");
		bizMap.put("/transaction/header/msg/sndTm", sndDt + sndTm.substring(0,6));
		LOGGER.info("向清算账户余额通知登记表te_ca_bal_notify插入一条数据，msgId={}",bizMap.get("/transaction/body/BalWrngNtfctn/GrpHdr/MsgId"));	
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		TeCaBalNotifyMapper teCaBalNotifyMapper = sqlSession.getMapper(TeCaBalNotifyMapper.class);
		teCaBalNotifyMapper.insertBalWarnNtc(bizMap);
	}
	
	/**
	 * 
	 * Description:NPS.360.001.01-清算账户余额透支报文
	 *
	 * @author yuzh
	 * @data 2019年8月24日
	 */
	private void clrgAcctBalOdNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.360.001.01-清算账户余额透支报文");
		String sndDt = bizMap.get("/transaction/header/msg/sndDt");
        String sndTm = bizMap.get("/transaction/header/msg/sndTm");
        bizMap.put("/transaction/header/msg/sndTm", sndDt + sndTm.substring(0,6));
        LOGGER.info("向清算账户余额通知登记表te_ca_bal_notify插入一条数据，msgId={}",bizMap.get("/transaction/body/BalNtfctn/GrpHdr/MsgId"));
        
        SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
        TeCaBalNotifyMapper teCaBalNotifyMapper = sqlSession.getMapper(TeCaBalNotifyMapper.class);
        teCaBalNotifyMapper.insertBalOdNtc(bizMap);
      
	}
	
	/**
	 * 
	 * Description:NPS.366.001.01-清算账户余额通知报文
	 *
	 * @author yuzh
	 * @data 2019年8月24日
	 */
	private void clrgAcctBalNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.366.001.01-清算账户余额通知报文");
		String sndDt = bizMap.get("/transaction/header/msg/sndDt");
        String sndTm = bizMap.get("/transaction/header/msg/sndTm");
        bizMap.put("/transaction/header/msg/sndTm", sndDt + sndTm.substring(0,6));
        LOGGER.info("向清算账户余额通知登记表te_ca_bal_notify插入一条数据，msgId={}",bizMap.get("/transaction/body/BalNtfctn/GrpHdr/MsgId"));
        
        SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
        TeCaBalNotifyMapper teCaBalNotifyMapper = sqlSession.getMapper(TeCaBalNotifyMapper.class);
        String ncsD = bizMap.get("/transaction/body/BalNtfctn/BalNtfctnInf/Detail/BizDt");
        if(StringUtils.isBlank(ncsD)){
            ncsD = bizMap.get("/transaction/body/BalNtfctn/BalNtfctnInf/Detail[1]/BizDt");
            bizMap.put("/transaction/body/BalNtfctn/BalNtfctnInf/Detail/BizDt",StringUtils.isBlank(ncsD) ? DateUtil.date3Str(new Date()) : ncsD);
        }
        teCaBalNotifyMapper.insertBalNtc(bizMap);
       
	}
	
	/**
	 * 
	 * Description:NPS.801.001.01-系统状态变更通知报文
	 *
	 * @author jjw
	 * @data 2019年8月24日
	 */
	private void sysStaUpdtNtc(Map<String,String> bizMap) throws Exception{
		
		LOGGER.info("开始处理NPS.801.001.01-系统状态变更通知报文");
		ToPChl toPChlQC = new ToPChl();
		toPChlQC.setpCId(SysEcodeEnum.NCS.getCode());
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToPChlMapper toPChlMapper = sqlSession.getMapper(ToPChlMapper.class);
		ToPChl toPChlQR = toPChlMapper.query(toPChlQC);
		LOGGER.info("支付通道信息表to_p_chl查询结果：toPChlQR={}",toPChlQR);
		
		Date curSysDt = DateUtil.str2Date(bizMap.get("/transaction/body/SysStsNtfctn/SysStsInf/CurSysDt"), "yyyy-MM-dd");
		String curSysSts = bizMap.get("/transaction/body/SysStsNtfctn/SysStsInf/CurSysSts");
		
		boolean flag = false;
		ToPChl toPChlUC = new ToPChl();
		if(!curSysDt.equals(toPChlQR.getpCD())){
			flag = true;
			toPChlUC.setpCD(curSysDt);
		}
		if(!curSysSts.equals(toPChlQR.getEnblSta())){
			flag = true;
			toPChlUC.setEnblSta(curSysSts);
		}
		
		if(flag){
			toPChlUC.setId(toPChlQR.getId());
			toPChlUC.setUpdTm(new Date());
			LOGGER.info("支付通道信息表to_p_chl更新字段：toPChlUC={}",toPChlUC);
			toPChlMapper.update(toPChlUC);
		}
		
		
	}
	
	/**
	 * 
	 * Description:NPS.807.001.01-强制离线通知报文
	 *
	 * @author jjw
	 * @data 2019年8月24日
	 */
	private void frcOflNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.807.001.01-强制离线通知报文");
		ToOrg toOrgUC = new ToOrg();
		toOrgUC.setOrgBNo(bizMap.get("/transaction/body/LogoutNtfctn/GrpHdr/InstdPty/InstdDrctPty"));
		toOrgUC.setOrgSta(MbrOStaEnum.LGT.getCode());
		toOrgUC.setUpdTm(new Date());
		LOGGER.info("应用机构信息表to_org更新字段：toOrgUC={}",toOrgUC);
		
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToOrgMapper toOrgMapper = sqlSession.getMapper(ToOrgMapper.class);
		toOrgMapper.update(toOrgUC);
		//刷新时间戳
		TpRefrshTblnm tblnm = new TpRefrshTblnm();
		tblnm.setTblNm("to_org");
		tblnm.setUpdtTime(DateUtil.getDateTime());
		sqlSession.getMapper(TpRefrshTblnmMapper.class).update(tblnm);

		
	}
	
	/**
	 * 
	 * Description:NPS.809.001.01-停启运通知
	 *
	 * @author jjw
	 * @data 2019年8月24日
	 */
	private void otlStrtupNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.809.001.01-停启运通知");
		ToPChl toPChlUC = new ToPChl();
		toPChlUC.setpCId(SysEcodeEnum.NCS.getCode());
		String enblSta = bizMap.get("/transaction/body/StopgNtfctn/StsInf/NewSts");
		toPChlUC.setEnblSta(enblSta);
		if(StatEnum.NCS_START.getCode().equals(enblSta)){
			toPChlUC.setpCBgnTm(bizMap.get("/transaction/body/StopgNtfctn/StsInf/FctvDt").replaceAll("-",""));
		}else if(StatEnum.NCS_809_STOP.getCode().equals(enblSta)){
			toPChlUC.setpCFinTm(bizMap.get("/transaction/body/StopgNtfctn/StsInf/FctvDt").replaceAll("-",""));
		}
		toPChlUC.setUpdTm(new Date());
		LOGGER.info("支付通道信息表to_p_chl更新字段：toPChlUC={}",toPChlUC);
		
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToPChlMapper toPChlMapper = sqlSession.getMapper(ToPChlMapper.class);
		toPChlMapper.update(toPChlUC);
		

	}
	
	/**
	 * 
	 * Description:NPS.803.001.01-成员机构状态变更通知
	 *
	 * @author jjw
	 * @data 2019年8月24日
	 */
	private void mbrOStaUpdtNtc(Map<String,String> bizMap){
		
		LOGGER.info("开始处理NPS.803.001.01-成员机构状态变更通知");
		String ptyTp = bizMap.get("/transaction/body/TrblNtfctn/StsInf/PtyTp");
		if(!MbrOTypEnum.MBR_O.getCode().equals(ptyTp)){
			LOGGER.info("成员机构类型={}，该类型不做处理",MbrOTypEnum.getNameByCode(ptyTp));
			return;
		}
		
		List<ToOrg> toOrgUCs = new ArrayList<ToOrg>();
		String orgSta = bizMap.get("/transaction/body/TrblNtfctn/StsInf/Tp");
		Set<Entry<String,String>> entrys = bizMap.entrySet();
		for(Entry<String,String> entry : entrys){
			if(!entry.getKey().contains("/transaction/body/TrblNtfctn/StsInf/PtyId")){
				continue;
			}
			ToOrg toOrgUC = new ToOrg();
			toOrgUC.setOrgBNo(entry.getValue());
			toOrgUC.setOrgSta(orgSta);
			toOrgUC.setUpdTm(new Date());
			toOrgUCs.add(toOrgUC);
		}
		LOGGER.info("应用机构信息表to_org更新列表：toOrgUCs={}",toOrgUCs);
		
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToOrgMapper toOrgMapper = sqlSession.getMapper(ToOrgMapper.class);
		toOrgMapper.batchUpdate(toOrgUCs);

	}
	
	
/**
 * 查询接收行系统编号	
 * @param bno
 * @return
 */
	/*public ToOrg queryBnoCls(String bno) {
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToOrgMapper toOrgMapper = sqlSession.getMapper(ToOrgMapper.class);
		ToOrg org = new ToOrg();
		org.setOrgBNo(bno);
		org = toOrgMapper.queryByBNo(org);
		LOGGER.info("查询到的机构信息：org={}",org.toString());
		return org;
	}*/
	
	
	public ToParm queryBnoCls(String bno,String parmType) {
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		ToParmMapper toParmMapper = sqlSession.getMapper(ToParmMapper.class);
		ToParm toParm = new ToParm();
		toParm.setDataVal(bno);
		toParm.setDataTyp(parmType);
		List<ToParm> list = toParmMapper.query(toParm);
		if(list != null){
			if(list.size()==1){
				return list.get(0);
			}else if(list.size()==0){
				return null;
			}else{
				throw new BaseException(RespCd.NCPO0007,String.format("参数信息表数据异常，类型:[%s],行号:[%s]",DataTypeEnum.BIZSYS.getCode(),bno));
			}
		}
		return null;

	}
	
	
	
	public void returnGwProc(String bizMsg,String sndAppCd) {
		String tpId = DtaInfo.getInstance().getTpId();
		String msgCd =XmlUtil.getValByXPath(bizMsg,"/transaction/header/msg/msgCd");
		
		EPOper.put(tpId, "ReqBean[0].head[0].rcvAppCd", sndAppCd);
		EPOper.put(tpId, "ReqBean[0].head[0].reqServCd", msgCd);
		EPOper.getCompSDO(tpId, "ReqBody").setValue("BizMsg",bizMsg);
		String rspsCd = RpcCommUtil.getInstance().rpcFeToGW(tpId, RpcOutputInfoEnum.OutputName_Pub_Cpfsgw.getCode(),RpcOutputInfoEnum.OutPutSvr_CpfsFwdThrdPrtS.getCode());	  
			
	}


	private void regToSysNtc(Map<String,String> bizMap){
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");
		LOGGER.info("开始处理通知类报文登记通知表to_sys_ntc");
	    bizMap.put("sndOrgNo", bizMap.get("/transaction/header/msg/sndMbrCd"));
		bizMap.put("recpOrgNo", bizMap.get("/transaction/header/msg/rcvMbrCd"));
		bizMap.put("seqNb",  bizMap.get("/transaction/header/msg/seqNb"));
		bizMap.put("ntcTyp", bizMap.get("/transaction/header/msg/msgCd"));
		bizMap.put("bizSta", StatEnum.BIZSTA_SUC.getCode());
		bizMap.put("ntcTm", DateUtil.getTimestamp(new Date()));
		ToSysNtcMapper toSysNtc = sqlSession.getMapper(ToSysNtcMapper.class);
		ToSysNtc tsn =toSysNtc.selectToSysNtc(bizMap);
		if(tsn==null){
			toSysNtc.insert(bizMap);
		}
	}

	public void returnNPS990(Map bizMap){
		String tpId = DtaInfo.getInstance().getTpId();
		//转发给网关
		try{
			String bizMsg990 = ResponseUtil.build990Xml(bizMap);
			LOGGER.debug("rpc调用网关发送NPS990开始......");
			EPOper.put(tpId, "ReqBean[0].head[0].rcvAppCd", SysEcodeEnum.NCS.getCode());
			EPOper.put(tpId, "ReqBean[0].head[0].reqServCd", MsgCdOrTpEnum.MSGCD_990.getCode());
			EPOper.getCompSDO(tpId, "ReqBody").setValue("BizMsg", bizMsg990);
			RpcCommUtil.getInstance().rpcFeToGW(tpId, RpcOutputInfoEnum.OutputName_Pub_Cpfsgw.getCode(),RpcOutputInfoEnum.OutPutSvr_CpfsFwdThrdPrtS.getCode());
		}catch(Exception e){
			LOGGER.error("调用网关转发NPS.990报文服务失败",e);
			throw new BaseException(RespCd.NCPO6047,e,"调用网关服务异常");
		}
	}

}
